/**
 * WebSocket客户端管理器
 */
const { io } = require('socket.io-client');
const logger = require('./logger');
const config = require('./config');
const EventEmitter = require('events');
const clientIdManager = require('./clientId'); // 🔥 导入客户端ID管理器

class WebSocketClient extends EventEmitter {
  constructor() {
    super();
    this.socket = null;
    this.connected = false;
    this.authenticated = false;
    this.reconnectAttempts = 0;
    this.maxReconnectAttempts = Infinity; // 🔥 无限重连
    this.reconnectDelay = 3000;
    this.heartbeatInterval = null; // 🔥 心跳定时器
    this.heartbeatTimeout = null; // 🔥 心跳超时定时器
    this.lastHeartbeatTime = null; // 🔥 最后心跳时间
    this.heartbeatTimeoutDuration = 60000; // 🔥 心跳超时时间：60秒
    this.isManualDisconnect = false; // 🔥 是否手动断开
  }

  /**
   * 连接到WebSocket服务器
   */
  connect() {
    return new Promise((resolve, reject) => {
      const url = config.getWebSocketUrl();
      logger.logWebSocket('尝试连接服务器', { url });

      this.isManualDisconnect = false; // 🔥 重置手动断开标志

      this.socket = io(url, {
        transports: ['websocket', 'polling'], // 🔥 先尝试websocket，失败则降级到polling
        reconnection: true, // 🔥 启用自动重连
        reconnectionDelay: this.reconnectDelay, // 🔥 重连延迟：3秒
        reconnectionDelayMax: 10000, // 🔥 最大重连延迟：10秒
        reconnectionAttempts: this.maxReconnectAttempts, // 🔥 无限重连
        timeout: 20000, // 🔥 连接超时：20秒
        forceNew: false, // 🔥 复用连接
        upgrade: true, // 🔥 允许从polling升级到websocket
        rememberUpgrade: true, // 🔥 记住升级，下次直接使用websocket
        pingTimeout: 60000, // 🔥 ping超时：60秒
        pingInterval: 25000 // 🔥 ping间隔：25秒（socket.io内置心跳）
      });

      // 连接成功
      this.socket.on('connect', () => {
        this.connected = true;
        this.reconnectAttempts = 0;
        logger.logWebSocket('连接成功');
        this.emit('connected');
        resolve();
      });

      // 连接错误
      this.socket.on('connect_error', (error) => {
        logger.logWebSocket('连接错误', { error: error.message });
        this.connected = false;
        this.emit('connection-error', error);
        
        if (this.reconnectAttempts === 0) {
          reject(error);
        }
      });

      // 断开连接
      this.socket.on('disconnect', (reason) => {
        this.connected = false;
        this.authenticated = false;
        this.stopHeartbeat(); // 🔥 停止心跳
        logger.logWebSocket('连接断开', { reason });
        this.emit('disconnected', reason);
      });

      // 重连尝试
      this.socket.on('reconnect_attempt', (attemptNumber) => {
        this.reconnectAttempts = attemptNumber;
        logger.logWebSocket(`重连尝试 ${attemptNumber}/${this.maxReconnectAttempts}`);
        this.emit('reconnecting', attemptNumber);
      });

      // 重连成功
      this.socket.on('reconnect', (attemptNumber) => {
        logger.logWebSocket(`重连成功，尝试次数: ${attemptNumber}`);
        this.emit('reconnected');
        
        // 🔥 重新认证，包含客户端ID
        const userConfig = config.getUserConfig();
        if (userConfig.userId && userConfig.username) {
          const clientId = clientIdManager.getClientId();
          this.authenticate(userConfig.userId, userConfig.username, clientId);
        }
      });

      // 监听通知
      this.socket.on('notification', (notification) => {
        logger.info('[通知] 收到通知', notification);
        this.emit('notification', notification);
      });

      // 监听传输进度
      this.socket.on('task-progress', (data) => {
        this.emit('task-progress', data);
      });

      // 监听任务状态变化
      this.socket.on('task-status-changed', (data) => {
        this.emit('task-status-changed', data);
      });

      // 监听FTP连接状态
      this.socket.on('ftp:connected', (data) => {
        this.emit('ftp-connected', data);
      });

      this.socket.on('ftp:disconnected', (data) => {
        this.emit('ftp-disconnected', data);
      });

      // 监听传输完成
      this.socket.on('transfer:completed', (data) => {
        this.emit('transfer-completed', data);
      });

      // 监听传输失败
      this.socket.on('transfer:failed', (data) => {
        this.emit('transfer-failed', data);
      });

      // 🔥 监听心跳响应
      this.socket.on('heartbeat-ack', () => {
        // 心跳响应成功，更新最后心跳时间
        this.lastHeartbeatTime = Date.now();
        this.resetHeartbeatTimeout();
        // 🔥 心跳响应日志改为debug级别，减少CPU占用
        logger.debug('[WebSocket] 心跳响应成功');
      });

      // 🔥 监听强制登出事件
      this.socket.on('force-logout', (data) => {
        logger.logWebSocket('收到强制登出事件', data);
        this.emit('force-logout', data);
      });

      // 🔥 监听服务器请求客户端目录
      this.socket.on('request-directory', (data, callback) => {
        logger.logWebSocket('收到请求目录事件', data);
        this.emit('request-directory', data, callback);
      });

      // 🔥 监听服务器下发传输任务
      this.socket.on('dispatch-transfer-task', (task, callback) => {
        logger.logWebSocket('收到传输任务下发', task);
        this.emit('dispatch-transfer-task', task, callback);
      });
    });
  }

  /**
   * 认证用户
   */
  authenticate(userId, username, clientId = null) {
    return new Promise((resolve, reject) => {
      if (!this.connected) {
        return reject(new Error('WebSocket未连接'));
      }

      logger.logWebSocket('发送认证请求', { userId, username, clientId });

      // 🔥 发送认证请求，包含clientId
      this.socket.emit('authenticate', { userId, username, clientId });

      this.socket.once('authenticated', (response) => {
        if (response.success) {
          this.authenticated = true;
          logger.logWebSocket('认证成功');
          this.startHeartbeat(); // 🔥 启动心跳
          this.emit('authenticated');
          resolve();
        } else {
          logger.logWebSocket('认证失败', { message: response.message });
          
          // 🔥 处理设备冲突
          if (response.code === 'ALREADY_LOGGED_IN') {
            this.emit('device-conflict', {
              message: response.message,
              currentClientId: response.current_client_id
            });
          }
          
          // 如果是401错误，触发未授权事件
          if (response.message && (response.message.includes('401') || response.message.includes('未授权') || response.message.includes('过期'))) {
            this.emit('unauthorized');
          }
          
          this.emit('auth-failed', response.message);
          reject(new Error(response.message || '认证失败'));
        }
      });
    });
  }

  /**
   * 🔥 启动心跳
   */
  startHeartbeat() {
    // 先停止之前的心跳
    this.stopHeartbeat();
    
    // 初始化最后心跳时间
    this.lastHeartbeatTime = Date.now();
    
    // 🔥 每20秒发送一次心跳（比socket.io的pingInterval稍短）
    this.heartbeatInterval = setInterval(() => {
      if (this.connected && this.authenticated) {
        this.socket.emit('heartbeat');
        // 🔥 心跳日志改为debug级别，减少CPU占用
        logger.debug('[WebSocket] 发送心跳');
        
        // 设置心跳超时检测
        this.setHeartbeatTimeout();
      } else if (!this.connected && !this.isManualDisconnect) {
        // 🔥 如果未连接且非手动断开，尝试重连
        logger.logWebSocket('检测到未连接状态，尝试重连...');
        if (this.socket && !this.socket.connected) {
          this.socket.connect();
        }
      }
    }, 20000);
    
    // 立即发送一次心跳
    if (this.connected && this.authenticated) {
      this.socket.emit('heartbeat');
      this.setHeartbeatTimeout();
    }
    
    logger.logWebSocket('心跳已启动（20秒间隔，超时检测60秒）');
  }

  /**
   * 🔥 设置心跳超时检测
   */
  setHeartbeatTimeout() {
    // 清除之前的超时定时器
    if (this.heartbeatTimeout) {
      clearTimeout(this.heartbeatTimeout);
    }
    
    // 设置新的超时定时器
    this.heartbeatTimeout = setTimeout(() => {
      const timeSinceLastHeartbeat = Date.now() - this.lastHeartbeatTime;
      logger.logWebSocket(`心跳超时！距上次心跳: ${timeSinceLastHeartbeat}ms`);
      
      // 🔥 心跳超时，触发重连
      if (!this.isManualDisconnect) {
        logger.logWebSocket('心跳超时，尝试重新连接...');
        this.emit('heartbeat-timeout');
        
        // 🔥 断开并重连
        if (this.socket) {
          try {
            this.socket.disconnect();
            setTimeout(() => {
              if (!this.isManualDisconnect) {
                this.socket.connect();
              }
            }, 1000); // 延迟1秒后重连
          } catch (error) {
            logger.logWebSocket('重连失败', { error: error.message });
          }
        }
      }
    }, this.heartbeatTimeoutDuration);
  }

  /**
   * 🔥 重置心跳超时定时器
   */
  resetHeartbeatTimeout() {
    if (this.heartbeatTimeout) {
      clearTimeout(this.heartbeatTimeout);
      this.heartbeatTimeout = null;
    }
  }

  /**
   * 🔥 停止心跳
   */
  stopHeartbeat() {
    if (this.heartbeatInterval) {
      clearInterval(this.heartbeatInterval);
      this.heartbeatInterval = null;
    }
    
    if (this.heartbeatTimeout) {
      clearTimeout(this.heartbeatTimeout);
      this.heartbeatTimeout = null;
    }
    
    logger.logWebSocket('心跳已停止');
  }

  /**
   * 发送传输进度
   */
  sendTransferProgress(taskId, transferred, speed) {
    if (this.connected && this.authenticated) {
      this.socket.emit('transfer-progress', { taskId, transferred, speed });
    }
  }

  /**
   * 发送传输状态
   */
  sendTransferStatus(taskId, status, errorMessage = null) {
    if (this.connected && this.authenticated) {
      this.socket.emit('transfer-status', { taskId, status, errorMessage });
    }
  }

  /**
   * 发送客户端日志
   */
  sendClientLog(level, message, stackTrace = null, clientTime = new Date()) {
    if (this.connected && this.authenticated) {
      this.socket.emit('client-log', { level, message, stackTrace, clientTime });
    }
  }

  /**
   * 断开连接
   */
  disconnect() {
    if (this.socket) {
      this.isManualDisconnect = true; // 🔥 标记为手动断开
      this.stopHeartbeat(); // 🔥 停止心跳
      this.socket.disconnect();
      this.socket = null;
      this.connected = false;
      this.authenticated = false;
      logger.logWebSocket('主动断开连接');
    }
  }

  /**
   * 获取连接状态
   */
  getStatus() {
    return {
      connected: this.connected,
      authenticated: this.authenticated,
      reconnectAttempts: this.reconnectAttempts
    };
  }
}

module.exports = new WebSocketClient();
